package com.yoki.cloud.common.protocol.radius.msg.packet.acct.req;

import com.yoki.cloud.common.protocol.radius.attribute.attr.RadiusMsgAttr;
import com.yoki.cloud.common.protocol.radius.attribute.attr.check.*;
import com.yoki.cloud.common.protocol.radius.attribute.parser.RadiusMsgAttrParser;
import com.yoki.cloud.common.protocol.radius.exception.RadiusException;
import com.yoki.cloud.common.protocol.radius.msg.packet.RadiusMsg;
import com.yoki.cloud.common.protocol.radius.msg.packet.ReqRadiusMsg;
import com.yoki.cloud.common.utils.encrypt.EncryptUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Sky$
 * @Description: TODO
 * @date 2018/1/12$ 9:33$
 */
public class AccountingRequestMsg extends ReqRadiusMsg {

    public static final int PACKET_CODE = 4;

    public AccountingRequestMsg(String secret) {
        super(secret);
        code = getPacketCode() ;
    }

    @Override
    public int getPacketCode() {
        return PACKET_CODE;
    }

    /**
     * Code + Identifier + Length + 16 zero octets + request attributes + shared secret
     *
     * @param byteWithoutAuthenticator 除了Authenticator的字节码
     * @return
     */
    @Override
    protected byte[] getAuthenticatorBytes(byte[] byteWithoutAuthenticator) {
        byte[] out = byteWithoutAuthenticator;
        byte[] requestAuthenticator = new byte[RadiusMsg.LENGTH_AUTHENTICATOR];
        byte[] secretBytes = secret.getBytes();

        byte[] tempBytes = new byte[out.length + secretBytes.length];

        System.arraycopy(out, 0, tempBytes, 0, out.length);
        System.arraycopy(requestAuthenticator, 0, tempBytes, INDEX_AUTHENTICATOR, LENGTH_AUTHENTICATOR);
        System.arraycopy(secretBytes, 0, tempBytes, out.length, secretBytes.length);
        return EncryptUtils.encryptMD5Bytes(tempBytes);
    }

    @Override
    protected void parseAttributes(List<byte[]> attrBytesList) throws RadiusException {
        if (null == attributes) {
            attributes = new ArrayList<>();
        }
        if (null == attrBytesList) {
            return;
        }
        //进行所有属性的解析
        for (byte[] attrBytes : attrBytesList) {
            int type = attrBytes[RadiusMsgAttr.INDEX_TYPE] & 0XFF;
            if (!typeLegal(type, true)) {
                continue;
            }
            RadiusMsgAttr attr = RadiusMsgAttrParser.parse(attrBytes);
            //加入属性列表中
            if (null != attr) {
                this.attributes.add(attr);
            }
        }
    }

    @Override
    protected List<byte[]> getAttributesBytesList() {
        List<byte[]> list = new LinkedList<>();
        if (null != attributes) {
            for (RadiusMsgAttr attr : attributes) {
                int type = attr.getAttrType();
                if (!typeLegal(type, true)) {
                    continue;
                }
                byte[] bytes = bytes = attr.getBytes();
                if (null != bytes) {
                    list.add(bytes);
                }
            }
        }
        return list;
    }

    @Override
    protected boolean typeLegal(int type, boolean print) {
        if ((type == UserPasswordAttr.ATTR_TYPE) || (type == ChapPasswordAttr.ATTR_TYPE)
                || (type == ReplyMessageAttr.ATTR_TYPE) || (type == StateAttr.ATTR_TYPE)
                || (type == ChapChallengeAttr.ATTR_TYPE)) {
            if (print) {
                System.out.println("Data can not be converted into this type of attribution , Type is inconsistent !!! " +
                        "Radius Accounting-Request packet required type can not be [ "
                        + UserPasswordAttr.ATTR_TYPE + " , " + ChapPasswordAttr.ATTR_TYPE + " , "
                        + ReplyMessageAttr.ATTR_TYPE + " , " + StateAttr.ATTR_TYPE + " , "
                        + ChapChallengeAttr.ATTR_TYPE
                        + " ]");
            }
            return false;
        }
        return true;
    }
}
